// Calculation_Calc1.cpp: Implementierungsdatei
//

#include "stdafx.h"
#include <math.h>
#include "Charplan.h"
#include "Calculation_Calc1.h"
#include "Charplandoc.h"
#include "LuaInterface.h"

// CCalculation_Calc1-Dialogfeld

IMPLEMENT_DYNCREATE(CCalculation_Calc1, CCalculationPage)

CCalculation_Calc1::CCalculation_Calc1(CWnd* pParent /*=NULL*/)
        : CCalculationPage(pParent)
{

}


// for runtime creations
BOOL CCalculation_Calc1::Create(CWnd* pParentWnd)
{
    return CDialog::Create(CCalculation_Calc1::IDD,pParentWnd);
}

CCalculation_Calc1::~CCalculation_Calc1()
{
}


void CCalculation_Calc1::DoDataExchange(CDataExchange* pDX)
{
    CCalculationPage::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_EVADE, mwnd_evade);
    DDX_Control(pDX, IDC_EDIT_ITEM11, mwnd_items_parry);
    DDX_Control(pDX, IDC_EDIT_ITEM12, mwnd_items_block);
    DDX_Control(pDX, IDC_PARRY, mwnd_parry);
    DDX_Control(pDX, IDC_BLOCK, mwnd_block);
    DDX_Control(pDX, IDC_PARRYEVADEBLOCK, mwnd_parry_block_evade);
    DDX_Control(pDX, IDC_PARRYEVADEBLOCK3, mwnd_parry_evade);
    DDX_Control(pDX, IDC_HITPOINTS, mwnd_base_hits);
    DDX_Control(pDX, IDC_EDIT_ITEM9, mwnd_hits_items);
    DDX_Control(pDX, IDC_EDIT_ITEM_CAP9, mwnd_hits_items_overcap);
    DDX_Control(pDX, IDC_HITPOINTS_TOTAL, mwnd_hits_total);
    DDX_Control(pDX, IDC_EDIT_ITEM13, mwnd_speed_buff);
    DDX_Control(pDX, IDC_EDIT_ITEM14, mwnd_speed_items);
    DDX_Control(pDX, IDC_WSPD_CELERITY, mwnd_speed_celerity);
    DDX_Control(pDX, IDC_WEAPONSPEED_FACTOR, mwnd_speed_factor);
    DDX_Control(pDX, IDC_WEAPONSPEED_CAP, mwnd_cap_speed);
    DDX_Control(pDX, IDC_WSPD_SPEEDTEST, mwnd_speed_test);
    DDX_Control(pDX, IDC_WEAPONSPEED_TEST, mwnd_speed_test_res);
    DDX_Control(pDX, IDC_COMBO1, mwnd_buffs_haste);
    DDX_Control(pDX, IDC_COMBO2, mwnd_buffs_cele);
    DDX_Control(pDX, IDC_COMBO3, mwnd_skill);
    DDX_Control(pDX, IDC_CHECK1, mwnd_use_alt_dex);
    DDX_Control(pDX, IDC_EDIT_ITEM10, mwnd_wskill_items);
    DDX_Control(pDX, IDC_WF_TOTAL, mwnd_wskill_total);
    DDX_Control(pDX, IDC_WF_TOTAL3, mwnd_ideal_dps);
    DDX_Control(pDX, IDC_SEPARATOR2, mwnd_separator[0]);
    DDX_Control(pDX, IDC_SEPARATOR3, mwnd_separator[1]);
    DDX_Control(pDX, IDC_SEPARATOR4, mwnd_separator[2]);
    DDX_Control(pDX, IDC_SEPARATOR5, mwnd_separator[3]);
}

BEGIN_MESSAGE_MAP(CCalculation_Calc1, CCalculationPage)
    ON_EN_CHANGE(IDC_EDIT_ITEM11, &CCalculation_Calc1::OnEnChangeEditItem11)
    ON_EN_KILLFOCUS(IDC_EDIT_ITEM11, &CCalculation_Calc1::OnEnKillfocusEditItem11)
    ON_EN_CHANGE(IDC_EDIT_ITEM12, &CCalculation_Calc1::OnEnChangeEditItem12)
    ON_EN_KILLFOCUS(IDC_EDIT_ITEM12, &CCalculation_Calc1::OnEnKillfocusEditItem12)
    ON_EN_CHANGE(IDC_EDIT_ITEM9, &CCalculation_Calc1::OnEnChangeEditItem9)
    ON_EN_KILLFOCUS(IDC_EDIT_ITEM9, &CCalculation_Calc1::OnEnKillfocusEditItem9)
    ON_EN_CHANGE(IDC_EDIT_ITEM_CAP9, &CCalculation_Calc1::OnEnChangeEditItemCap9)
    ON_EN_KILLFOCUS(IDC_EDIT_ITEM_CAP9, &CCalculation_Calc1::OnEnKillfocusEditItemCap9)
    ON_EN_CHANGE(IDC_EDIT_ITEM13, &CCalculation_Calc1::OnEnChangeEditItem13)
    ON_EN_CHANGE(IDC_EDIT_ITEM14, &CCalculation_Calc1::OnEnChangeEditItem14)
    ON_EN_KILLFOCUS(IDC_EDIT_ITEM13, &CCalculation_Calc1::OnEnKillfocusEditItem13)
    ON_EN_KILLFOCUS(IDC_EDIT_ITEM14, &CCalculation_Calc1::OnEnKillfocusEditItem14)
    ON_CBN_SELCHANGE(IDC_COMBO1, &CCalculation_Calc1::OnCbnSelchangeCombo1)
    ON_CBN_SELCHANGE(IDC_COMBO2, &CCalculation_Calc1::OnCbnSelchangeCombo2)
    ON_CBN_SELCHANGE(IDC_COMBO3, &CCalculation_Calc1::OnCbnSelchangeCombo3)
    ON_EN_CHANGE(IDC_EDIT_ITEM10, &CCalculation_Calc1::OnEnChangeEditItem10)
    ON_EN_KILLFOCUS(IDC_EDIT_ITEM10, &CCalculation_Calc1::OnEnKillfocusEditItem10)
    ON_EN_CHANGE(IDC_WSPD_CELERITY, &CCalculation_Calc1::OnEnChangeEditItem15)
    ON_EN_KILLFOCUS(IDC_WSPD_CELERITY, &CCalculation_Calc1::OnEnKillfocusEditItem15)
    ON_EN_CHANGE(IDC_WSPD_SPEEDTEST, &CCalculation_Calc1::OnEnChangeEditItem16)
    ON_BN_CLICKED(IDC_CHECK1, &CCalculation_Calc1::OnBnClickedCheck1)
END_MESSAGE_MAP()



//////////////////////////////////////////////////////////////////////////
BOOL CCalculation_Calc1::OnInitDialog()
{
    CCalculationPage::OnInitDialog();
    mwnd_use_alt_dex.SetCheck(0!=GETOPTIONDEF("ALTERNATIVE_DEX",0));

    UpdatePoints(); // <- check if needed
    return TRUE;
}

//////////////////////////////////////////////////////////////////////////
void CCalculation_Calc1::SetupToolTips()
{
    CCalculationPage::SetupToolTips();

    mToolTips.AddTool(&mwnd_speed_items,IDS_STATS_FORMAT_HASTE_ITEM);
    mToolTips.AddTool(&mwnd_speed_buff,IDS_STATS_FORMAT_HASTE_BUFF);
    mToolTips.AddTool(&mwnd_speed_celerity,IDS_STATS_FORMAT_CELERITY_BUFF);
    mToolTips.AddTool(&mwnd_cap_speed,IDS_STATS_FORMAT_SPEED_OPTIMUM);
    mToolTips.AddTool(&mwnd_speed_test,IDS_STATS_FORMAT_WEAPON_SPEED);
    mToolTips.AddTool(&mwnd_use_alt_dex,IDS_ALT_DEX_CALC);
}


//////////////////////////////////////////////////////////////////////////
void CCalculation_Calc1::UpdatePoints(bool updateuseroption /*= true*/)
{
    UpdatePointsEvade(updateuseroption);
    UpdatePointsHitpoints(updateuseroption);
    UpdatePointsWeaponspeed(updateuseroption);
    UpdatePointsWeaponskill(updateuseroption);

    GetPage()->FillSummary();
}


void CCalculation_Calc1::OnPointsChanged()
{
    UpdatePoints(false);
}


void CCalculation_Calc1::OnClassChanged()
{
    OnClassChangedHaste();
    OnClassChangedWSkill();
}

void CCalculation_Calc1::OnRRChanged()
{
    UpdatePointsWeaponskill(false);
}



void CCalculation_Calc1::OnBnClickedCheck1()
{
    SETOPTION("ALTERNATIVE_DEX",(mwnd_use_alt_dex.GetCheck()==BST_CHECKED?1:0));
    GetDocument()->p_lua->OnUserOptionChanged();
    UpdatePointsEvade(false);
}


//////////////////////////////////////////////////////////////////////////
// Evade
//////////////////////////////////////////////////////////////////////////
void CCalculation_Calc1::UpdatePointsEvade(bool updateuseroption /*= true*/)
{

    CString temp,description_text;

    CCharplanDoc* pdoc = GetDocument();
    CPage1* page = GetPage();
    CLuaInterface* plua = GetDocument()->p_lua;

    int item_cap = page->GetCap(CPage1::EHH_CAP_ITEM_SKILL);
    int parry_items = GetOption(_T("BI_10"),item_cap);
    int block_items = GetOption(_T("BI_11"),item_cap);
    parry_items = CLAMP(parry_items,0,item_cap);
    block_items = CLAMP(block_items,0,item_cap);


    // M.Jurkait [5/1/2006]
    // -------------------------
    // user setting edit-fields
    // -------------------------
    if (updateuseroption)
    {
        description_text.LoadString(IDS_STATS_ITEM_BONUS_SKILL);

        // PArry - Item Bonus
        temp.Format(_T("%i"),parry_items);
        mwnd_items_parry.SetWindowText(temp);
        mToolTips.UpdateTipText(description_text,&mwnd_items_parry);

        // Block - Item Bonus
        temp.Format(_T("%i"),block_items);
        mwnd_items_block.SetWindowText(temp);
        mToolTips.UpdateTipText(description_text,&mwnd_items_block);
    }



    // -------------------------
    // evade / block / parry
    // -------------------------
    {
        // evade
        mwnd_evade.SetWindowText( pdoc->TextFormat("${evade.chance;.2} %"));

        if (plua->Test("evade.chance ~=0"))  description_text = pdoc->TextFormat(IDS_STATS_FORMAT_EVADE);
        else                                 description_text.LoadString(IDS_STATS_FORMAT_EVADE_NO);

        mToolTips.UpdateTipText(description_text,&mwnd_evade);


        // parry
        mwnd_parry.SetWindowText( pdoc->TextFormat("${parry.chance;.2} %"));

        if (plua->Test("class.can_parry"))  description_text = pdoc->TextFormat(IDS_STATS_FORMAT_PARRY);
        else                                description_text.LoadString(IDS_STATS_NO_PARRY);

        mToolTips.UpdateTipText(description_text,&mwnd_parry);


        // block
        mwnd_block.SetWindowText( pdoc->TextFormat("${block.chance;.2} %"));

        if (plua->Test("block.chance ~=0"))  description_text = pdoc->TextFormat(IDS_STATS_FORMAT_BLOCK);
        else                                 description_text.LoadString(IDS_STATS_FORMAT_BLOCK_NO);

        mToolTips.UpdateTipText(description_text,&mwnd_block);


        // total
        mwnd_parry_block_evade.SetWindowText( plua->Eval("chance_to_defend,' %'").c_str());
        mwnd_parry_evade.SetWindowText( plua->Eval("chance_to_evade_parry,' %'").c_str());
        mToolTips.UpdateTipText(pdoc->TextFormat(IDS_STATS_FORMAT_EVADE_BLOCK),&mwnd_parry_block_evade);
        mToolTips.UpdateTipText(pdoc->TextFormat(IDS_STATS_FORMAT_EVADE_PARRY),&mwnd_parry_evade);
    }


    GetPage()->FillSummary();
}


void CCalculation_Calc1::OnEnChangeEditItem11()    { EditCtrlChanged(&mwnd_items_parry,_T("BI_10"),CPage1::EHH_CAP_ITEM_SKILL,false); GetDocument()->p_lua->OnUserOptionChanged(); UpdatePointsEvade(false);}
void CCalculation_Calc1::OnEnKillfocusEditItem11() { EditCtrlChanged(&mwnd_items_parry,_T("BI_10"),CPage1::EHH_CAP_ITEM_SKILL,true);  GetDocument()->p_lua->OnUserOptionChanged(); UpdatePointsEvade(false);}
void CCalculation_Calc1::OnEnChangeEditItem12()    { EditCtrlChanged(&mwnd_items_block,_T("BI_11"),CPage1::EHH_CAP_ITEM_SKILL,false); GetDocument()->p_lua->OnUserOptionChanged(); UpdatePointsEvade(false);}
void CCalculation_Calc1::OnEnKillfocusEditItem12() { EditCtrlChanged(&mwnd_items_block,_T("BI_11"),CPage1::EHH_CAP_ITEM_SKILL,true);  GetDocument()->p_lua->OnUserOptionChanged(); UpdatePointsEvade(false);}



//////////////////////////////////////////////////////////////////////////
//  Hitpoints
//////////////////////////////////////////////////////////////////////////
void CCalculation_Calc1::UpdatePointsHitpoints(bool updateuseroption /*= true*/)
{
    CString description_text;
    CCharplanDoc* pdoc = GetDocument();


    // M.Jurkait [5/1/2006]
    // -------------------------
    // user setting edit-fields
    // -------------------------
    if (updateuseroption)
    {
        CPage1* page = GetPage();
        CString temp;

        int hp_cap = page->GetCap(CPage1::EHH_CAP_HP_BONUS);
        int hp_over_cap = page->GetCap(CPage1::EHH_CAP_HP_BONUS_OVERCAP);
        int hp_items = pdoc->GetOption(_T("BI_8"),hp_cap);
        int hp_items_overcap = pdoc->GetOption(_T("BICAP_8"),hp_over_cap);
        hp_items = CLAMP(hp_items,0,hp_cap);
        hp_items_overcap = CLAMP(hp_items_overcap,0,hp_over_cap);

        // HP - Item Bonus
        temp.Format(_T("%i"),hp_items);
        mwnd_hits_items.SetWindowText(temp);
        description_text.LoadString(IDS_STATS_ITEM_BONUS);
        mToolTips.UpdateTipText(description_text,&mwnd_hits_items);

        // HP - Item Bonus over CAP
        temp.Format(_T("%i"),hp_items_overcap);
        mwnd_hits_items_overcap.SetWindowText(temp);
        description_text.LoadString(IDS_STATS_ITEM_BONUS_CAP);
        mToolTips.UpdateTipText(description_text,&mwnd_hits_items_overcap);
    }


    /////////////////////////////////////
    mwnd_base_hits.SetWindowText( pdoc->TextFormat("${hitpoints.sum1}"));
    description_text = pdoc->TextFormat(IDS_STATS_FORMAT_TP_ATLEVEL50);
    mToolTips.UpdateTipText(description_text,&mwnd_base_hits);


    mwnd_hits_total.SetWindowText( pdoc->TextFormat("${hitpoints.total}"));
    description_text = pdoc->TextFormat(IDS_STATS_FORMAT_TP_ATLEVEL_FINAL);
    mToolTips.UpdateTipText(description_text,&mwnd_hits_total);

    GetPage()->FillSummary();
}


void CCalculation_Calc1::OnEnChangeEditItem9()       { EditCtrlChanged(&mwnd_hits_items,_T("BI_8"),CPage1::EHH_CAP_HP_BONUS,false); GetDocument()->p_lua->OnUserOptionChanged();  UpdatePointsHitpoints(false);}
void CCalculation_Calc1::OnEnKillfocusEditItem9()    { EditCtrlChanged(&mwnd_hits_items,_T("BI_8"),CPage1::EHH_CAP_HP_BONUS,true);  GetDocument()->p_lua->OnUserOptionChanged();  UpdatePointsHitpoints(false);}
void CCalculation_Calc1::OnEnChangeEditItemCap9()    { EditCtrlChanged(&mwnd_hits_items_overcap,_T("BICAP_8"),CPage1::EHH_CAP_HP_BONUS_OVERCAP,false); GetDocument()->p_lua->OnUserOptionChanged();  UpdatePointsHitpoints(false);}
void CCalculation_Calc1::OnEnKillfocusEditItemCap9() { EditCtrlChanged(&mwnd_hits_items_overcap,_T("BICAP_8"),CPage1::EHH_CAP_HP_BONUS_OVERCAP,true); GetDocument()->p_lua->OnUserOptionChanged();  UpdatePointsHitpoints(false);}




//////////////////////////////////////////////////////////////////////////
// Weaponspeed
//////////////////////////////////////////////////////////////////////////

void CCalculation_Calc1::UpdatePointsWeaponspeed(bool updateuseroption /*= true*/)
{

    CString temp,description_format,description_text;

    CPage1* page = GetPage();
    CCharplanDoc* pdoc = GetDocument();



    int hast_buff= pdoc->GetOption(_T("HA_1"),0);
    int hast_item = pdoc->GetOption(_T("HA_2"),0);
    int hast_celerity = pdoc->GetOption(_T("HA_3"),0);

    // M.Jurkait [5/1/2006]
    // -------------------------
    // user setting edit-fields
    // -------------------------
    if (updateuseroption)
    {

        // hast buff
        temp.Format(_T("%i"),hast_buff);
        mwnd_speed_buff.SetWindowText(temp);

        // hast items
        temp.Format(_T("%i"),hast_celerity);
        mwnd_speed_celerity.SetWindowText(temp);

        // hast items
        temp.Format(_T("%i"),hast_item);
        mwnd_speed_items.SetWindowText(temp);
    }



    // Maik Jurkait [12/29/2006]
    // ------------------------
    // Weapon Speed
    // ------------------------
    {
        double qui = page->GetStat(CPage1::ESTATS_TOTAL,CPage1::ESTAT_QUI);
        if (qui>250)  qui=250; // hard cap

        double qui_factor = (100.0-(qui-50.0)/5.0); // by Solomon (was (qui-!60!) )
        double buff_factor = (100.0-(hast_buff + hast_item + hast_celerity));
        mf_speed_factor = qui_factor * buff_factor / 10000.0;

        temp.Format(_T("%.3g %%"),mf_speed_factor*100);
        mwnd_speed_factor.SetWindowText(temp);

        description_format.LoadString(IDS_STATS_FORMAT_SPEED_FACTOR);
        description_text.Format(description_format,qui_factor,buff_factor,mf_speed_factor*100.0);
        mToolTips.UpdateTipText(description_text,&mwnd_speed_factor);


        double capspd = 1.5/mf_speed_factor;
        int cs = (int)(capspd*10.0-1.0); // -0.1 because rounding's
        temp.Format(_T("%.3g"),cs/10.0);
        mwnd_cap_speed.SetWindowText(temp);
    }

    OnEnChangeEditItem16();
}


void CCalculation_Calc1::OnEnChangeEditItem16()
{
    CString text;
    mwnd_speed_test.GetWindowText(text);
    double val = _tstof(text);
    if (val==0)
    {
        mwnd_cap_speed.GetWindowText(text);
        val =_tstof(text);

        val = GetDocument()->GetOption(_T("WPSPD"),int(val*100)) / 100.0;

        if (val>0)
        {
            text.Format(_T("%.3g"),val);
            mwnd_speed_test.SetWindowText(text);
        }
    }

    if (val>0)
        GetDocument()->SetOption(_T("WPSPD"),int(val*100));


    double sp1 = val * mf_speed_factor;
    double sp2 = (val+0.1) * mf_speed_factor;
    if (sp1<1.5) sp1 =1.5;
    if (sp2<1.5) sp2 =1.5;

    if (sp1==sp2) text.Format(_T("%.3g"),sp1);
    else   text.Format(_T("%.3g - %.3g"),sp1,sp2);
    mwnd_speed_test_res.SetWindowText(text);

    CString description_format,description_text;

    description_format.LoadString(IDS_STATS_FORMAT_WEAPON_REAL_SPEED);
    description_text.Format(description_format,val,text);
    mToolTips.UpdateTipText(description_text,&mwnd_speed_test_res);

}




void CCalculation_Calc1::OnEnChangeEditItem13()  { EditCtrlChanged(&mwnd_speed_buff,_T("HA_1"),40,false);  UpdatePointsWeaponspeed(false);}
void CCalculation_Calc1::OnEnChangeEditItem14()  { EditCtrlChanged(&mwnd_speed_items,_T("HA_2"),40,false);  UpdatePointsWeaponspeed(false);}
void CCalculation_Calc1::OnEnChangeEditItem15()  { EditCtrlChanged(&mwnd_speed_celerity,_T("HA_3"),40,false); UpdatePointsWeaponspeed(false);}
void CCalculation_Calc1::OnEnKillfocusEditItem13() { EditCtrlChanged(&mwnd_speed_buff,_T("HA_1"),40,true);  UpdatePointsWeaponspeed(false);}
void CCalculation_Calc1::OnEnKillfocusEditItem14() { EditCtrlChanged(&mwnd_speed_items,_T("HA_2"),40,true);  UpdatePointsWeaponspeed(false);}
void CCalculation_Calc1::OnEnKillfocusEditItem15() { EditCtrlChanged(&mwnd_speed_celerity,_T("HA_3"),40,true); UpdatePointsWeaponspeed(false);}



void CCalculation_Calc1::AddBuffSpell(const CString& cat_name, bool base, bool self, CComboBox* pwnd)
{

    // M.Jurkait [6/13/2006]
    // -------------------------
    // Get spells
    // -------------------------
    if (base) gdbinterface.SelectSpellCatBase(cat_name);
    else  gdbinterface.SelectSpellCatSpec(cat_name);

    CStringArray names;
    IntArray levels;
    IntArray ids;

    gdbinterface.GetListOfSpells(&names,&levels,&ids);

    // M.Jurkait [6/13/2006]
    // -------------------------
    // check if this is self buff
    // -------------------------
    gdbinterface.SelectSpellID(ids[0]);
    bool is_self=false;
    CStringArray key,val;
    gdbinterface.GetSpellDescription(key,val);
    ASSERT(key[2]=="Target");
    if (val[2]=="Self" || val[2]=="Selbst") is_self = true;
#ifdef _DEBUG
    else
    {
        ASSERT(
            val[2]=="Enemy" || val[2]=="Group" || val[2]=="Friend" || val[2]=="Realm" ||
            val[2]=="Feind" || val[2]=="Gruppe" || val[2]=="Freund" || val[2]=="Reich"
        );
    }
#endif


    if (is_self && !self) return;


    // find buffer
    int buffer_id = 0;
    CString buffer = gdbinterface.GetClassName().c_str();
    if (is_self && self) buffer = _T("-self-");



    // Maik Jurkait [2/17/2007]
    // ------------------------
    // add all spells to combo
    // ------------------------
    for (int t=0;t<names.GetCount();t++)
    {
        gdbinterface.SelectSpellID(ids[t]);
        CString eff = gdbinterface.GetSpellDescriptionEffect();

        // get the value
        int pos = eff.Find("%");
        if (pos==-1)
        {
            TRACE("Warn: celerity spell don't have %%: %s",(LPCSTR)eff);
            continue;
        }
        pos--;
        while (pos>=0 && isdigit(eff[pos]))   pos--;
        pos++;
        int value = _tstoi(eff.Mid(pos));


        CString entry;
        entry.Format("+%2i %s (lvl %i)",value,buffer,levels[t]);

        // find insert position
        pos=0;
        for (;pos<pwnd->GetCount();++pos)
            if ((int)(pwnd->GetItemData(pos))>value) break;

        int idx = pwnd->InsertString(pos,entry);
        pwnd->SetItemData(idx,value);
    }
}




//////////////////////////////////////////////////////////////////////////
void CCalculation_Calc1::OnClassChangedHaste()
{
    // Maik Jurkait [2/17/2007]
    // ------------------------
    // Clear
    // ------------------------
    mwnd_buffs_haste.ResetContent();
    mwnd_buffs_cele.ResetContent();


    // Maik Jurkait [2/17/2007]
    // ------------------------
    // Backup database state
    // ------------------------
    int current_class = gdbinterface.GetClassID();
    int current_race = gdbinterface.GetRaceID();


    // Maik Jurkait [2/17/2007]
    // ------------------------
    // Check all spells
    // ------------------------
    IntArray class_ids;
    gdbinterface.GetListOfClasses(class_ids);


    for (int cl=0;cl<class_ids.GetCount();cl++)
    {
        gdbinterface.SelectClass(class_ids[cl]);

        bool self_allowed = (class_ids[cl]==current_class);

        CStringArray spell_lines;
        gdbinterface.GetListOfSpellLines(spell_lines);

        for (int spl=0;spl<spell_lines.GetCount();spl++)
        {
            gdbinterface.SelectSpellLine(spell_lines[spl]);

            CStringArray spell_cats;
            IntArray  spell_types;

            // Base
            gdbinterface.GetListOfSpellCatsBaseAndID(spell_cats, spell_types);

            for (int spc=0;spc<spell_cats.GetCount();spc++)
            {
                if (spell_types[spc] == STI_BUFF_COMBAT_SPEED)
                {
                    AddBuffSpell(spell_cats[spc], true, self_allowed,&mwnd_buffs_haste);
                }
                else
                    if (spell_types[spc] == STI_BUFF_CELERITY)
                    {
                        AddBuffSpell(spell_cats[spc], true, self_allowed,&mwnd_buffs_cele);
                    }
            }

            // Spec
            gdbinterface.GetListOfSpellCatsSpecAndID(spell_cats, spell_types);

            for (int spc=0;spc<spell_cats.GetCount();spc++)
            {
                if (spell_types[spc] == STI_BUFF_COMBAT_SPEED)
                {
                    AddBuffSpell(spell_cats[spc], false, self_allowed,&mwnd_buffs_haste);
                }
                else
                    if (spell_types[spc] == STI_BUFF_CELERITY)
                    {
                        AddBuffSpell(spell_cats[spc], false, self_allowed,&mwnd_buffs_cele);
                    }
            }
        }
    }

    // Maik Jurkait [2/17/2007]
    // ------------------------
    // reset selection
    // ------------------------
    gdbinterface.SelectClass(current_class);
    gdbinterface.SelectRace(current_race);
}




void CCalculation_Calc1::OnCbnSelchangeCombo1()
{
    // buff changed
    int buf_id = mwnd_buffs_haste.GetCurSel();
    if (buf_id == CB_ERR) return;

    int val = (int)mwnd_buffs_haste.GetItemData(buf_id);

    SetOption(_T("HA_1") , val);
    UpdatePoints(true);
}



void CCalculation_Calc1::OnCbnSelchangeCombo2()
{
    // buff changed
    int buf_id = mwnd_buffs_cele.GetCurSel();
    if (buf_id == CB_ERR) return;

    int val = (int)mwnd_buffs_cele.GetItemData(buf_id);

    SetOption(_T("HA_3") , val);
    UpdatePoints(true);
}



//////////////////////////////////////////////////////////////////////////
// Weaponskill
//////////////////////////////////////////////////////////////////////////
void CCalculation_Calc1::OnClassChangedWSkill()
{
    CStringArray names;
    IntArray  levels;
    IntArray  type;

    gdbinterface.GetListOfAbilities(names,levels,type);

    mwnd_skill.ResetContent();


    for (int t=0;t<names.GetCount();t++)
    {
        // check if normal or enhanced
        CString temp = names[t];
        temp.MakeLower();

        if (type[t]>15)
        {
            int idx = mwnd_skill.AddString(names[t]);
            mwnd_skill.SetItemData(idx,type[t]>>4);
        }
        else
        if (temp=="archery" || temp=="bogen") 
        {
            int idx = mwnd_skill.AddString(names[t]);
            mwnd_skill.SetItemData(idx,4);
        }

    }


    // M.Jurkait [5/1/2006]
    // -------------------------
    // Select skill
    // -------------------------
    int max_id = -1;
    int max_skill = -1;
    for (int t=0;t<mwnd_skill.GetCount();t++)
    {
        CString temp;
        mwnd_skill.GetLBText(t,temp);

        int n = GetDocument()->GetSpecLevel(temp);
        if (n>max_skill)
        {
            max_skill = n;
            max_id = t;
        }
    }

    mwnd_skill.SetCurSel(max_id);


}




void CCalculation_Calc1::UpdatePointsWeaponskill(bool updateuseroption /*= true*/)
{
    CString temp,description_format,description_text;

    CPage1* page = GetPage();
    CCharplanDoc* pdoc = GetDocument();


    int item_cap = page->GetCap(CPage1::EHH_CAP_ITEM_SKILL);
    int wf_items = pdoc->GetOption(_T("BI_9"),item_cap);
    wf_items = CLAMP(wf_items,0,item_cap);


    // M.Jurkait [5/1/2006]
    // -------------------------
    // user setting edit-fields
    // -------------------------
    if (updateuseroption)
    {

        // WF - Item Bonus
        temp.Format(_T("%i"),wf_items);
        mwnd_wskill_items.SetWindowText(temp);
        description_text.LoadString(IDS_STATS_ITEM_BONUS_SKILL);
        mToolTips.UpdateTipText(description_text,&mwnd_wskill_items);

    }


    // M.Jurkait [5/1/2006]
    // -------------------------
    // WF
    // -------------------------
    {
        // get skill and type
        int skill = 0;
        int type = 0;

        int idx = mwnd_skill.GetCurSel();
        if (idx != CB_ERR)
        {
            mwnd_skill.GetLBText(idx,temp);
            type= (int)mwnd_skill.GetItemData(idx);

            skill = pdoc->GetSpecLevel(temp);
        }





        int str_real = page->GetStat(CPage1::ESTATS_TOTAL,CPage1::ESTAT_STR) & ~1;
        int dex_real = page->GetStat(CPage1::ESTATS_TOTAL,CPage1::ESTAT_DEX) & ~1;
        int strdex = ((str_real+dex_real)>>2)*2;

        // get class values
        int tab_basewf, tab_basewf_b;
        double tab_wffactor, tab_wffactor_b;
        gdbinterface.GetClassesWFModifier(tab_basewf,tab_wffactor,tab_basewf_b,tab_wffactor_b);

        CString s_type(_T("error"));
        int base_wf = 0;
        switch (type)
        {
            case 0: // none (error)
                break;

            case 1: // STR
                base_wf = (int)floor(0.5 + (str_real-50)*tab_wffactor+tab_basewf);
                s_type = _T("STR");
                break;

            case 2: // DEX
                base_wf = (int)floor(0.5 + (dex_real-50)*tab_wffactor+tab_basewf);
                s_type = _T("DEX");
                break;

            case 3: // STR+DEX
                base_wf = (int)floor(0.5 + (strdex-50)*tab_wffactor+tab_basewf);
                s_type = _T("STR & DEX");
                break;

            case 4: // BOW (dex)
                base_wf = (int)floor(0.5 + (dex_real-50)*tab_wffactor_b+tab_basewf_b);
                s_type = _T("DEX");
                break;
        }

        // skill + RR
        int rr_skill = page->GetRRSkill();
        skill += rr_skill;

        int wf = (int)floor(0.5+base_wf*(1+ (skill+wf_items*19.0/11.0)/100.0));


        temp.Format(_T("%i"),wf);
        mwnd_wskill_total.SetWindowText(temp);

        if (base_wf >0)
        {
            description_format.LoadString(IDS_STATS_FORMAT_WEAPONABILITY);
            description_text.Format(description_format,
                                    type!=4?tab_basewf:tab_basewf_b,
                                    base_wf - (type!=4?tab_basewf:tab_basewf_b),s_type,
                                    (skill+wf_items*19.0/11.0),skill-rr_skill,rr_skill,wf_items,
                                    wf
                                   );
        }
        else
            description_text.LoadString(IDS_STATS_FORMAT_WEAPONABILITY_NO);

        mToolTips.UpdateTipText(description_text,&mwnd_wskill_total);
    }

    // Maik Jurkait [1/9/2007]
    // ------------------------
    // Ideal DPS
    // ------------------------
    {
        int level = (int)(pdoc->GetLevel());
        double dps = level * 0.3f + 1.2;
        if (GetDocument()->GetRR()>39) dps += 0.3;

        temp.Format(_T("%g"), dps);
        mwnd_ideal_dps.SetWindowText(temp);
    }


    GetPage()->FillSummary();
}




void CCalculation_Calc1::OnCbnSelchangeCombo3()  { UpdatePointsWeaponskill(false);}
void CCalculation_Calc1::OnEnChangeEditItem10()  { EditCtrlChanged(&mwnd_wskill_items,_T("BI_9"),CPage1::EHH_CAP_ITEM_SKILL,false); UpdatePointsWeaponskill(false);}
void CCalculation_Calc1::OnEnKillfocusEditItem10() { EditCtrlChanged(&mwnd_wskill_items,_T("BI_9"),CPage1::EHH_CAP_ITEM_SKILL,true); UpdatePointsWeaponskill(false);}



